<?php
class Debugger
{
	/**
	 * Devuelve la pila de llamadas (stack).
	 */
	private function stack()
	{
		return( $this->overrideDebugger(debug_backtrace()) );
	}

	/**
	 * Devuelve un frame de la pila, a partir de su índice.
	 *
	 * @param number Indice del stack frame.
	 */
	private function getStackFrame($number)
	{
		$stack = $this->stack();

		if ( count($number) > count($stack) )
			return(null);

		return ( $stack[$number] );
	}

	/**
	 * Elimina de la pila las llamadas correspondientes
	 * a la instancia actual de las clases hijas, y al
	 * depurador mismo.
	 */
	private function overrideDebugger($stack)
	{
		$stackClean = array();
		$class = get_class($this);

		for ( $i = 0; $i < count($stack); $i++ ) {
			$stackFrame = $stack[$i];

			if ( ($stackFrame["class"] != "Debugger") &&
				 ($stackFrame["class"] != $class))
				array_push($stackClean, $stackFrame);
		}

		return( $stackClean );
	}

	/**
	 * Devuelve el nombre de la función que llamó al
	 * procedimiento que ejecuta callee. Opcionalmente
	 * se puede consultar otras llamadas de la pila.
	 *
	 * @param baseFrame Índice del stack frame a recuperar.
	 */
	protected function callee($baseFrame = 0)
	{
		$frame = $this->getStackFrame($baseFrame);

		return( $frame["function"] );
	}

	/**
	 * Devuelve el nombre de la clase que creó la instancia
	 * del objeto que llamó al procedimiento que ejecuta caller.
	 * Opcionalmente se puede consultar otras llamadas de la pila.
	 *
	 * @param baseFrame Índice del stack frame a recuperar.
	 */
	protected function caller($baseFrame = 0)
	{
		$frame = $this->getStackFrame($baseFrame);

		return( $frame["class"] );
	}

	/**
	 * Devuelve el objeto StackFrame (dinámico) correspondiente
	 * al frame del índice especificado.
	 *
	 * @param baseFrame Índice del stack frame a recuperar.
	 */
	protected function dbgGetFrame($baseFrame = 0)
	{
		$debugObj = new DynamicObject();
		$frame = $this->getStackFrame($baseFrame);

		if ( !is_array($frame) )
			return(null);

		foreach ( array_keys($frame) as $item ) {
			$debugObj->$item = $frame[$item];
		}

		return($debugObj);
	}
}
?>
